import hashlib
from lxml import etree
from urllib import parse
import time, requests, json
from django.conf import settings
from django.core.cache import cache
from collections import OrderedDict

class Wechat:

    appid = settings.WECHAT_KEY['AppId']
    appsecret = settings.WECHAT_KEY['AppSecret']
    data = {}
    accessToken = ''

    def __init__(self):
        access_token_cache = cache.get('access_token_cache')
        if access_token_cache:
            self.accessToken = access_token_cache
        else:
            self.accessToken = self.get_AccessToken()
            cache.set('access_token_cache', self.accessToken, 7000)
        #print(cache.get('access_token_cache'))

    def start(self, request):
        parser = etree.XMLParser(recover=True)
        xmlData = etree.fromstring(request.body.decode('utf-8'), parser=parser)
        for element in xmlData:
            self.data[element.tag] = element.text.replace(' ![CDATA[', '').replace('] ]>', '').strip()

    def auth(self, token, request):
        sign = request.GET['signature']
        timestamp = request.GET['timestamp']
        nonce = request.GET['nonce']
        list = [token, timestamp, nonce]
        list.sort()
        sha = hashlib.sha1()
        sha.update("".join(list).encode('utf-8'))
        return sign == sha.hexdigest()

    def replayText(self, content):
        xml = self.MsgToXml('text')
        Content = etree.SubElement(xml, 'Content')
        Content.text = etree.CDATA(content)
        return etree.tostring(xml, pretty_print=True, encoding="utf-8")

    def replayImage(self, media_id):
        xml = self.MsgToXml('image')
        Image = etree.SubElement(xml, 'Image')
        MediaId = etree.SubElement(Image, 'MediaId')
        MediaId.text = etree.CDATA(media_id)
        return etree.tostring(xml, pretty_print=True).decode('utf-8').replace('\n', '')

    def replayNews(self, data):
        xml = self.MsgToXml('news')
        ArticleCount = etree.SubElement(xml, 'ArticleCount')
        ArticleCount.text = '1'
        Articles = etree.SubElement(xml, 'Articles')
        item = etree.SubElement(Articles, 'item')
        Title = etree.SubElement(item, 'Title')
        Title.text = etree.CDATA(data['title'])
        Description = etree.SubElement(item, 'Description')
        Description.text = etree.CDATA(data['description'])
        PicUrl = etree.SubElement(item, 'PicUrl')
        PicUrl.text = etree.CDATA(data['PicUrl'])
        Url = etree.SubElement(item, 'Url')
        Url.text = etree.CDATA(data['url'])
        return etree.tostring(xml, pretty_print=True, encoding="utf-8")

    def MsgToXml(self, type):
        xml = etree.Element("xml")
        ToUserName = etree.SubElement(xml, 'ToUserName')
        ToUserName.text = etree.CDATA(self.data['FromUserName'])
        FromUserName = etree.SubElement(xml, 'FromUserName')
        FromUserName.text = etree.CDATA(self.data['ToUserName'])
        CreateTime = etree.SubElement(xml, 'CreateTime')
        CreateTime.text = etree.CDATA(str(time.time()))
        MsgType = etree.SubElement(xml, 'MsgType')
        MsgType.text = etree.CDATA(type)
        return xml

    def get_qrcode(self, id):
        data = {"action_name": "QR_LIMIT_SCENE", "action_info": {"scene": {"scene_id": ""}}}
        data['action_info']['scene']['scene_id'] = id
        r = requests.post(
            'https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=' + self.accessToken,
            data=json.dumps(data))
        url = 'https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket='+ parse.quote(r.json()['ticket'])
        qr = requests.get(url)
        return qr.content

    def get_AccessToken(self):
        url = 'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={}&secret={}'.format(self.appid, self.appsecret)
        r = requests.get(url)
        return r.json()['access_token']

    #拉取会员信息
    def getMemberInfo(self, card_id, card_code):
        url = 'https://api.weixin.qq.com/card/membercard/userinfo/get?access_token=' + self.accessToken
        data = {
            'card_id': card_id,
            'code': card_code
        }
        r = requests.post(url, data=json.dumps(data))
        return r.json()

    #新增永久素材（除图文消息外）
    def createMedia(self, media, type):
            #self.accessToken = '12_48qJVaepBh9gd71-ZnzvpfBBvX_V4NKAIFZ3r6EiI63hCjduN5a9mP8I1cX6qWCxb1LdMhuEFTEpAX_XPlM0M88vJFAPORZw0tho8grfglC1aot05sxyO74Ev7XQrmzsXC7IKUJA85L020L1FEAdACAAZV'
        url = 'https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=' + self.accessToken + '&type=' + type
        r = requests.post(url, files=media)
        return r.json()

    #获取jsapi_ticket
    def getJsApiTicket(self):
        jsapi_ticket = cache.get('jsapi_ticket_cache')
        if jsapi_ticket:
            return jsapi_ticket
        else:
            url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={}&type=jsapi'.format(self.accessToken)
            r = requests.get(url)
            jsapi_ticket_cache = r.json()['ticket']
            cache.set('jsapi_ticket_cache', jsapi_ticket_cache, 7000)
            return jsapi_ticket_cache

    #JSAPI签名
    def jsapiSign(self, timestamp, nonceStr, url):
        dict = {
            'jsapi_ticket': self.getJsApiTicket(),
            'timestamp': timestamp,
            'nonceStr': nonceStr,
            'url': url
        }
        return self.sign(dict)

    #api_ticket
    def getApiTicket(self):
        api_ticket = cache.get('api_ticket_cache')
        if api_ticket:
            return api_ticket
        else:
            url = 'https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={}&type=wx_card'.format(self.accessToken)
            r = requests.get(url)
            api_ticket_cache = r.json()['ticket']
            cache.set('jsapi_ticket_cache', api_ticket_cache, 7000)
            return api_ticket_cache

    #签名
    def sign(self, data):
        data_sort = sorted(data)
        dict = {}
        for i in data_sort:
            dict[i] = data[i]
        dict_str = parse.urlencode(dict)
        sha = hashlib.sha1(dict_str.encode('utf8'))
        return sha.hexdigest()
